import time
import hmac
import hashlib
import base64
import urllib.parse
import             print(f"📡 请求URL: {self.endpoint}")
            print(f"📋 请求参数: Action={params['Action']}, ProductKey={product_key}, DeviceName={device_name}")
            print(f"⏰ 时间范围: {params['StartTime']} ~ {params['EndTime']}")
            print(f"📊 响应状态: {response.status_code}")uests
from datetime import datetime
from tenacity import retry, stop_after_attempt, wait_exponential

class AliyunIoTConnector:
    """修正版阿里云IoT设备连接器 - 使用QueryDevicePropertyData API"""
    
    def __init__(self, access_key_id, access_key_secret, region_id="cn-shanghai"):
        self.access_key_id = access_key_id
        self.access_key_secret = access_key_secret
        self.region_id = region_id
        # 修正：使用阿里云物联网平台的正确端点
        self.endpoint = f"https://iot.{region_id}.aliyuncs.com"
        self.last_data = {}
        self.last_fetch_time = 0
    
    def test_connection(self):
        """测试阿里云API端点可达性"""
        try:
            response = requests.get(self.endpoint, timeout=5)
            print(f"✅ 连接测试成功! 端点: {self.endpoint}, 状态码: {response.status_code}")
            return True
        except Exception as e:
            print(f"❌ 连接测试失败: {str(e)}")
            return False
    
    def _sign_request(self, params):
        """生成阿里云API签名"""
        # 1. 参数排序
        sorted_params = sorted(params.items())
        
        # 2. 构造规范化字符串
        canonicalized_query_string = urllib.parse.urlencode(sorted_params)
        
        # 3. 构造签名字符串  
        string_to_sign = "POST&%2F&" + urllib.parse.quote(canonicalized_query_string, safe="")
        
        # 4. 计算签名
        key = self.access_key_secret + "&"
        signature = hmac.new(key.encode("utf-8"), string_to_sign.encode("utf-8"), hashlib.sha1).digest()
        return base64.b64encode(signature).decode("utf-8")
    
    @retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=2, max=10))
    def get_device_data(self, product_key, device_name):
        """获取设备最新数据 - 使用QueryDevicePropertyData API"""
        try:
            # 计算时间范围（获取最近1小时的数据）
            end_time = datetime.utcnow()
            start_time = end_time.replace(hour=end_time.hour-1) if end_time.hour > 0 else end_time.replace(hour=23, day=end_time.day-1)
            
            # 构造请求参数
            params = {
                "Action": "QueryDevicePropertyData",
                "ProductKey": product_key,
                "DeviceName": device_name,
                "StartTime": start_time.strftime("%Y-%m-%d %H:%M:%S"),  # 必需参数：开始时间
                "EndTime": end_time.strftime("%Y-%m-%d %H:%M:%S"),      # 必需参数：结束时间
                "PageSize": "50",  # 必需参数：每页记录数
                "CurrentPage": "1",  # 可选参数：当前页码
                "Asc": "0",  # 0=降序，1=升序（获取最新数据）
                "Format": "JSON",
                "Version": "2018-01-20",
                "AccessKeyId": self.access_key_id,
                "SignatureMethod": "HMAC-SHA1",
                "Timestamp": datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ"),
                "SignatureVersion": "1.0",
                "SignatureNonce": str(int(time.time() * 1000000))  # 微秒级时间戳
            }
            
            # 生成签名
            params["Signature"] = self._sign_request(params)
            
            # 发送POST请求
            response = requests.post(
                self.endpoint,
                data=params,  # 使用data而不是params
                timeout=10,
                headers={'Content-Type': 'application/x-www-form-urlencoded'}
            )
            
            print(f"📡 请求URL: {self.endpoint}")
            print(f"� 请求参数: Action={params['Action']}, ProductKey={product_key}, DeviceName={device_name}")
            print(f"�📊 响应状态: {response.status_code}")
            
            if response.status_code == 200:
                data = response.json()
                print(f"📄 响应数据: {data}")
                
                if data.get("Success"):
                    parsed_data = self._parse_device_data(data.get("Data", {}))
                    self.last_data = parsed_data
                    self.last_fetch_time = time.time()
                    return parsed_data
                else:
                    error_msg = data.get('Message', 'Unknown error')
                    error_code = data.get('Code', 'Unknown')
                    print(f"⚠️ API返回错误: [{error_code}] {error_msg}")
                    return self.last_data  # 返回缓存数据
            else:
                print(f"❌ 请求失败: {response.status_code} - {response.text}")
                return self.last_data  # 返回缓存数据
                
        except Exception as e:
            print(f"❌ 获取设备数据失败: {e}")
            return self.last_data  # 返回缓存数据
    
    def _parse_device_data(self, raw_data):
        """解析设备数据"""
        parsed = {}
        
        # 处理数据结构: {"List": {"PropertyInfo": [...]}}
        property_list = raw_data.get("List", {}).get("PropertyInfo", [])
        
        if not property_list and "PropertyInfo" in raw_data:
            # 备用数据结构处理
            property_list = raw_data["PropertyInfo"]
        
        for item in property_list:
            identifier = item.get("Identifier")
            value = item.get("Value")
            if identifier and value is not None:
                parsed[identifier] = value
        
        print(f"🔄 解析数据: {len(parsed)} 个属性")
        return parsed


class SimpleDeviceConnector:
    """兼容旧接口的简化设备连接器"""
    
    def __init__(self, access_key_id, access_key_secret, product_key, device_name, region='cn-shanghai'):
        self.access_key_id = access_key_id
        self.access_key_secret = access_key_secret
        self.product_key = product_key
        self.device_name = device_name
        self.region = region
        
        # 创建核心连接器
        self.connector = AliyunIoTConnector(access_key_id, access_key_secret, region)
        self.last_data = {}
        self.last_fetch_time = 0
    
    def test_connection(self):
        """测试连接"""
        return self.connector.test_connection()
    
    def get_device_property(self, identifier):
        """获取设备单个属性"""
        data = self.get_device_data_batch([identifier])
        return data.get(identifier)
    
    def get_device_data_batch(self, identifiers=None):
        """获取设备数据"""
        # 如果最近5秒内获取过数据，直接返回缓存
        if time.time() - self.last_fetch_time < 5:
            return self.last_data
        
        # 获取完整设备数据
        raw_data = self.connector.get_device_data(self.product_key, self.device_name)
        
        if identifiers:
            # 过滤指定的标识符
            filtered_data = {}
            for identifier in identifiers:
                if identifier in raw_data:
                    filtered_data[identifier] = raw_data[identifier]
            return filtered_data
        
        self.last_data = raw_data
        self.last_fetch_time = time.time()
        return raw_data
    
    def fetch_data(self):
        """获取所有关键设备数据（兼容旧接口）"""
        # 定义要获取的关键属性
        key_identifiers = [
            "radar_heartrate", "radar_breath", "radar_body_exist", "sleep_state",
            "radar_sleep_score", "heartrate", "body_movement", "pose", "sleeping",
            "turn_over", "sitting_up", "temp", "humidity", "brightness", "dB",
            "servoangle", "servospeed", "heat", "sleep_wake_hour", "sleep_light_hour",
            "sleep_deep_hour", "sleepflag", "LightSwitch"
        ]
        
        # 获取原始数据
        raw_data = self.get_device_data_batch()
        
        # 解析并返回标准格式
        return self._parse_device_data(raw_data)
    
    def _parse_device_data(self, raw_data):
        """解析阿里云返回的设备数据（根据物模型）"""
        # 根据物模型定义映射关系
        mapping = {
            # 人体数据
            'radar_heartrate': ('heart_rate', int),
            'radar_breath': ('breath_rate', int),
            'radar_body_exist': ('body_exist', bool),
            'sleep_state': ('sleep_state', int),
            'radar_sleep_score': ('sleep_score', int),
            'heartrate': ('heart_rate_secondary', int),
            'body_movement': ('body_movement', int),
            'pose': ('pose', int),
            'sleeping': ('sleeping', bool),
            'turn_over': ('turn_over', int),
            'sitting_up': ('sitting_up', bool),
            
            # 环境数据
            'temp': ('temperature', int),
            'humidity': ('humidity', int),
            'brightness': ('brightness', int),
            'dB': ('noise_level', int),
            
            # 床板数据
            'servoangle': ('servo_angle', int),
            'servospeed': ('servo_speed', int),
            'heat': ('heat_level', int),
            
            # 睡眠分析
            'sleep_wake_hour': ('wake_hours', float),
            'sleep_light_hour': ('light_sleep_hours', float),
            'sleep_deep_hour': ('deep_sleep_hours', float),
            
            # 其他
            'sleepflag': ('sleep_flag', int),
            'LightSwitch': ('light_switch', bool)
        }
        
        parsed = {}
        for identifier, value in raw_data.items():
            if identifier in mapping:
                field_name, field_type = mapping[identifier]
                try:
                    # 特殊处理布尔值
                    if field_type == bool:
                        if isinstance(value, str):
                            parsed[field_name] = value.lower() in ['true', '1', 'yes', 'on']
                        else:
                            parsed[field_name] = bool(value)
                    # 处理其他类型
                    else:
                        parsed[field_name] = field_type(value) if value is not None else None
                except (ValueError, TypeError):
                    parsed[field_name] = None
            else:
                # 保留未映射的字段
                parsed[identifier] = value
        
        return parsed
    
    def get_specific_data(self, identifier):
        """获取特定标识符的数据"""
        return self.last_data.get(identifier)
    
    @retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=2, max=10))
    def get_device_data(self, identifiers):
        """获取设备最新数据（多个属性）"""
        try:
            # 直接获取全部数据，然后过滤
            all_data = self.get_device_data_batch()
            
            result = {}
            for identifier in identifiers:
                if identifier in all_data:
                    result[identifier] = all_data[identifier]
                    
            return result
            
        except Exception as e:
            print(f"❌ 获取设备数据失败: {e}")
            # 返回缓存数据
            return self.last_data


# 向后兼容的类别名
RealDeviceConnector = SimpleDeviceConnector
